local Signal = require"base.signal"
local fsm = class("FSM",Signal){
    _state = {main = "",parallel = {}},
    _change_table = {
        --[[
            main_state = {
                change = {},
                parallel = {},
            }

            parallel_state = {
                state = [true | false]--切换到这个状态时是否会清除此状态(如果有)
            }
        --]]
    },
}:reg()

function fsm:__init__(change_table)
    self._change_table = change_table or {}
    self:signal("change_state")
    self:signal("add_state")
    self:signal("remove_state")
end

function fsm:is_state(state)
    return (self._state.main == state) or (_state.parallel[state] ~= nil)
end

local function clear_pal(self)
    for pal_state in pairs(self._state.parallel) do
        local ps = self._change_table.parallel[pal_state]
        if ps then
            if ps ~= "*no" then
                if ps == "*all" then
                    self._state.parallel[pal_state] = nil
                    self:emit_signal("remove_state",pal_state)
                else
                    if ps[main_state] then
                        self._state.parallel[pal_state] = nil
                        self:emit_signal("remove_state",pal_state)
                    end
                end
            end
        else
            self._state.parallel[pal_state] = nil
            self:emit_signal("remove_state",pal_state)
        end
    end
end

function fsm:change_state(main_state)
    if self._state.main then
        local ss = self._change_table[main_state]
        local ms = self._change_table[self._state.main]
        if ss then
            if ms == "*no" then return end
            if ms == "*all" or ms.change[main_state] then
                self:emit_signal("change_state",self._state.main,main_state)
                self:emit_signal("remove_state",self._state.main)
                self._state.main = main_state
                clear_pal(self)
            end
        end
    else
        self:emit_signal("change_state",nil,main_state)
        self._state.main = main_state
    end
end

function fsm:add_state(parallel_state)
    if self._state.parallel[parallel_state] == nil then
        self._state.parallel[parallel_state] = true
        self:emit_signal("add_state")
    end
end

function fsm:remove_state(state,cls)
    if cls then
        self:clear_state()
    else
        self._state[state] = nil
    end
end

function fsm:clear_state()
    self._state = {}
end

return fsm